package com.tr.syscms.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tr.common.util.*;
import com.tr.syscms.entity.User;
import com.tr.syscms.mapper.UserMapper;
import com.tr.syscms.service.UserService;
import com.tr.syscms.utils.ConstantPropertiesUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.crypto.hash.Sha512Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author xiijava
 * @since 2022-06-07
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public Result login(User user) {
        String userName = user.getUserName();
        String password = user.getPassword();
        if (StrUtil.isEmpty(userName) || StrUtil.isEmpty(password)) {
            throw new CustomException(ResultStatus.ERROR.getReturncode(),
                    ResultStatus.ERROR.getReturnMessage());
        }
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("user_name", user.getUserName());
        User userLogin = baseMapper.selectOne(userQueryWrapper);
        if (userLogin != null) {
            String jwtToken = JwtUtils.getJwtToken(String.valueOf(userLogin.getUserId()), String.valueOf(userLogin.getUserName()));
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            log.info("Token值：{}", jwtToken);
            redisTemplate.opsForValue().set(jwtToken, userLogin, 60, TimeUnit.MINUTES);
            HashMap<String, String> map = new HashMap<>();
            map.put("token", jwtToken);
            map.put("userId", userLogin.getUserId().toString());
            return new Result(200, "登录成功！", map);
        }
        return new Result(500, "登录失败！", null);
    }

    @Override
    public User queryUserByUserName(String userName) {
        //实例化参数
        Map map = new HashMap();
        map.put("userName", userName);
        map.put("status", 0);
        map.put("delFlag", 0);
        //查询
        List<User> userList = userMapper.queryAll(map);
        //判断是否为空
        if (CollUtil.isNotEmpty(userList)) {
            return userList.get(0);
        }
        return null;
    }

    /**
     * 通过Map作为筛选条件分页查询
     *
     * @param map
     * @return
     */
    @Override
    public PageInfo queryAll(Map map) {
        if (map.get("pageNo") == null || map.get("pageSize") == null) {
            throw new CustomException(ResultStatus.NOT_ALLOWED_ACCESS.getReturncode(),
                    ResultStatus.NOT_ALLOWED_ACCESS.getReturnMessage());
        }
        Integer pageNo = Integer.valueOf(map.get("pageNo") + "");
        Integer pageSize = Integer.valueOf(map.get("pageSize") + "");
        //设值页码和每页显示数量
        PageHelper.startPage(pageNo, pageSize);
        //默认查询非删除用户
        map.put("delFlag", "0");
        //使用查询结果，构造PageInfo
        PageInfo pageInfo = new PageInfo(this.userMapper.queryAll(map));
        return pageInfo;
    }

    /**
     * 通过ID查询单条数据
     *
     * @param userId 主键
     * @return 实例对象
     */
    @Override
    public User queryById(Integer userId) {
        return this.userMapper.queryById(userId);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<User> queryAllByLimit(int offset, int limit) {
        return this.userMapper.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param user 实例对象
     * @return 实例对象
     */
    @Override
    public User insert(User user) {
        //获取原始密码
        String password = user.getPassword();
        //随机盐值
        String slat = UUID.randomUUID().toString().substring(0, 15);
        //计算密码
        Sha512Hash sha512Hash = new Sha512Hash(password, slat, BusinessConstant.CredentialsMatcher.HASH_ITERATIONS);
        //设置盐值
        user.setSalt(slat);
        //设置密码
        user.setPassword(sha512Hash.toString());
        user.setDelFlag("0");
        //设置更新时间
        user.setUpdateTime(new Date());
        this.userMapper.insert(user);
        return user;
    }

    /**
     * 修改数据
     *
     * @param user 实例对象
     * @return 实例对象
     */
    @Override
    public User update(User user) {
        this.userMapper.update(user);
        return this.queryById(user.getUserId());
    }

    /**
     * 通过主键删除数据
     *
     * @param userId 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer userId) {
        return this.userMapper.deleteById(userId) > 0;
    }

    /**
     * 上传文件
     *
     * @param file
     * @return
     */
    @Override
    public String uploadUserHeadPic(MultipartFile file) {
        //使用阿里云OSS官方文档api

        // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1（杭州）为例，Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
        String endpoint = ConstantPropertiesUtil.END_POINT;
        // 阿里云账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维，请登录RAM控制台创建RAM用户。
        String accessKeyId = ConstantPropertiesUtil.ACCESS_KEY_ID;
        String accessKeySecret = ConstantPropertiesUtil.ACCESS_KEY_SECRET;
        // 填写Bucket名称，例如examplebucket。
        String bucketName = ConstantPropertiesUtil.BUCKET_NAME;
        // 填写文件名。文件名包含路径，不包含Bucket名称。例如exampledir/exampleobject.txt。
//        String objectName = "exampledir/exampleobject.txt";

        OSS ossClient = null;
        try {
            // 创建OSSClient实例。
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

//            String content = "Hello OSS";
            //获得上传文件的输入流
            InputStream inputStream = file.getInputStream();
            //调用oss方法实现上传ossClient.putObject里面有三个参数
//            第一个参数 buctet名称
//            二  上传oss文件路径和文件名称
//            三  文件的输入流

//            获得文件名称
            String filename = file.getOriginalFilename();

            //如果文件名字相同的话 会覆盖文件  所以使用uuid    替换字符串
            String uuid = UUID.randomUUID().toString().replace("-", "");
            filename = uuid + filename;
            //文件按照日期做分类 url中/为文件夹分级  这里使用依赖工具类
            //构建日期路径：avatar/2019/02/26/文件名.jpg
            String filePath = new DateTime().toString("yyyy/MM/dd");
            filename = filePath + "/" + filename;

            //执行上传
            ossClient.putObject(bucketName, filename, inputStream);

            //获取 拼接url地址

            String uploadUrl = "http://" + bucketName + "." + endpoint + "/" + filename;

            //返回全部路径用于存储数据库中
            return uploadUrl;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
